/* 
 *  <copyright file="InputGameService.cs" company="Wesley Jowitt">
 *  
 *  SobrietyEngine: Copyright (c) 2011 Wesley Jowitt
 *  
 *  This software is distributed under a software license.
 *   * As of the creation time of this file, the license in use is the Microsoft Permissive License (Ms-PL) 
 *    * The license can be viewed at:
 *     * License.Txt in the root folder of this project
 *      * http://sobrietyengine.codeplex.com/license
 *       * http://www.microsoft.com/opensource/licenses.mspx
 *       
 *  </copyright>
 *   */

using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

using SobrietyEngine.Events;
using SobrietyEngine.Events.Input;
using SobrietyEngine.Input.Devices;

namespace SobrietyEngine.Input
{
    public class InputGameService:GameComponent
    {
        #region Input Data

        private GamePadState[] CurrentGamepadStates = new GamePadState[4];
        private GamePadState[] LastGamepadStates = new GamePadState[4];

        private GamePadCapabilities[] gamePadCapabilities = new GamePadCapabilities[4];
        #endregion

        #region ChargeSwitch Durations
        private const float deadZoneChargeSwitchDuration = 2f;
        private const float exitChargeSwitchDuration = 2f;
        #endregion

        #region ChargeSwitches
        private ChargeSwitchExit exitSwitch = 
            new ChargeSwitchExit(exitChargeSwitchDuration);
        private ChargeSwitchDeadZone deadZoneSwitch = 
            new ChargeSwitchDeadZone(deadZoneChargeSwitchDuration);
        #endregion

        #region Dead Zone Data
        private GamePadDeadZone deadZone = GamePadDeadZone.IndependentAxes;
        public GamePadDeadZone DeadZone
        {
            get { return deadZone; }
            set
            {
                deadZone = value;
            }
        }
        /*
        private string deadZoneString;
        private Vector2 deadZoneStringPosition;
        private Vector2 deadZoneStringCenterPosition;
         * */
        #endregion

        //for events
        IEventRouter eventRouterGameService;
        int MaxGamepads = 4;
        Boolean[] ConnectedGamepads;

        List<IInputDevice> inputTranslators = new List<IInputDevice>();

        public InputGameService(Microsoft.Xna.Framework.Game game):base(game)
        {
            ConnectedGamepads = new bool[MaxGamepads];
            Game.Services.AddService(typeof(InputGameService), this);
        }

        public override void Initialize()
        {
            base.Initialize();
            //for the event system
            eventRouterGameService = (IEventRouter)Game.Services.GetService(typeof(IEventRouter));
            //add keyboard and mouse as default            
            IInputDevice keyboard = new KeyboardDevice(eventRouterGameService);
            inputTranslators.Add(keyboard);
            eventRouterGameService.RaiseEvent(this, new DeviceConnected(keyboard));

            CheckDevices();
        }

        public void CheckDevices()
        {
            //poll for change in state of gamepads
            for (int gPad = 0; gPad < MaxGamepads; ++gPad)
            {
                CurrentGamepadStates[gPad] = GamePad.GetState((PlayerIndex)gPad, deadZone);
                if (CurrentGamepadStates[gPad].IsConnected && ConnectedGamepads[gPad] == false)
                {
                    //create the input device
                    ConnectedGamepads[gPad] = true;
                    IInputDevice device = new GamepadDevice(eventRouterGameService, gPad);
                    inputTranslators.Add(device);
                    //send the event
                    DeviceConnected df = new DeviceConnected(device);
                    eventRouterGameService.RaiseEvent(this, df);                    
                }
                else if (!CurrentGamepadStates[gPad].IsConnected && ConnectedGamepads[gPad] == true)
                {
                    ConnectedGamepads[gPad] = false;
                    IInputDevice toRemove = null;
                    foreach (IInputDevice i in inputTranslators)
                    {
                        if (i.Gamepad == true && i.GamepadIndex == gPad)
                        {
                            toRemove = i;
                        }
                    }

                    if (toRemove != null)
                    {
                        DeviceDisconnected df = new DeviceDisconnected(toRemove);
                        eventRouterGameService.RaiseEvent(this, df);
                        inputTranslators.Remove(toRemove);
                    }
                }
            }           
        }

    
        public override void Update(GameTime gameTime)
        {
            foreach(IInputDevice i in inputTranslators)
                i.Update(gameTime);
        }

    }
}